package com.rainbow.jwt;

import cn.hutool.core.util.StrUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Component;

import java.time.Instant;
import java.time.ZonedDateTime;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.stream.Collectors;

/**
 * @Author rainbow
 **/
@Component
public class TokenUtils {

    // secret 秘钥
    private final String SECRET = "auth_rainbow";

    // token有效期
    private final long VALIDATE_MINUTE = 30;

    // 加密算法
    private final Algorithm algorithm;


    public TokenUtils() {
        algorithm = Algorithm.HMAC256(SECRET);
    }

    /**
     * 根据用户信息生成token
     *
     * @param authentication
     * @return
     */
    public String generateToken(Authentication authentication) {
        String authorities = authentication.getAuthorities()
                .stream()
                .map(authority -> ((GrantedAuthority) authority).getAuthority())
                .collect(Collectors.joining(","));

        Date now = Date.from(Instant.now());

        Date expiration = Date.from(ZonedDateTime.now().plusMinutes(VALIDATE_MINUTE).toInstant());

        // 创建jwt
        return JWT.create()
                .withClaim("authorities", authorities)
                .withSubject(authentication.getName())
                .withIssuedAt(now)
                .withExpiresAt(expiration)
                .sign(algorithm);

    }

    /**
     * 验证token有效性
     *
     * @param token
     * @return
     */
    public boolean validateToken(String token) {
        if (token.isEmpty()) {
            return false;
        }
        try {
            JWT.require(algorithm).build().verify(token);
            return true;
        } catch (JWTVerificationException e) {
            return false;
        }
    }


    /**
     * 从token中解析用户信息
     *
     * @param token
     * @return
     */
    public Authentication getAuthentication(String token) {
        DecodedJWT decodedJWT = JWT.decode(token);

        String authorityString = decodedJWT.getClaim("authorities").asString();

        Collection<? extends GrantedAuthority> authorities = Collections.emptyList();

        if (!StrUtil.isEmpty(authorityString)) {
            authorities = Arrays.stream(authorityString.split(","))
                    .map(SimpleGrantedAuthority::new).collect(Collectors.toList());

            User principal = new User(decodedJWT.getSubject(), "", authorities);

            return new UsernamePasswordAuthenticationToken(principal, "", authorities);
        }
        return null;
    }


}
